package com.wswy.wzcx.ui.fkdj

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.text.TextUtils
import android.text.format.DateFormat
import com.blankj.utilcode.util.SPUtils
import com.che.libcommon.utils.ToastUtils
import com.che.libcommon.utils.optional.Optional
import com.wswy.wzcx.AppContext
import com.wswy.wzcx.api.Api
import com.wswy.wzcx.model.coupon.CouponResp
import com.wswy.wzcx.model.fkdj.FineExtraFeeResp
import com.wswy.wzcx.model.fkdj.FinePaymentDetail
import com.wswy.wzcx.model.reSend
import com.wswy.wzcx.module.GlobalConfigManager
import com.wswy.wzcx.module.base.*
import com.wswy.wzcx.statistics.StatTools
import com.wswy.wzcx.statistics.StatisticsId
import com.wswy.wzcx.ui.pay.PreFineInfo
import com.wswy.wzcx.utils.StringUtils
import io.reactivex.Single
import io.reactivex.functions.BiFunction
import io.reactivex.observers.DisposableObserver
import io.reactivex.subjects.PublishSubject
import java.util.concurrent.TimeUnit

class FineViewModel : PayViewModel() {

    data class FinePayConfig(var quickPayment: Boolean = false,

                             var quickFee: Float = 0f)


    private companion object {

        //默认罚款代缴单号，上次位支付的
        private const val KEY_LAST_FINENO = "key_last_fineno"

        private val noPrefix = arrayOf(31, 11, 13, 34, 35, 44, 45, 50, 52, 62, 22, 23, 32, 36, 41, 42, 43, 46, 14, 15, 21, 37, 51, 61, 63, 64, 12, 33, 53, 64, 65)
    }

    var fineQueryCount = 0
        private set

    private val checkFineLiveData = MutableLiveData<Resource<FinePaymentDetail?>>()

    private val preFineInfoLiveData = SingleLiveData<Resource<PreFineInfo?>>()

    private var lastCheckNo: String? = null

    private val fineLiveData = MutableLiveData<FineData>().apply {
        value = FineData()
    }

    //优惠券
    private val couponRespLiveData = MutableLiveData<Resource<CouponResp?>>()

    private val areaHintLiveData = SingleLiveData<String?>()

    private val extraFeeLiveData = PublishSubject.create<FineData>()

    private val quickDealLiveData = MutableLiveData<FinePayConfig>().apply {
        value = FinePayConfig()
    }

    override fun onCreate() {
        super.onCreate()

        val extraFeeObserver = object : DisposableObserver<Optional<FineExtraFeeResp>>() {

            override fun onNext(s: Optional<FineExtraFeeResp>) {

                s.orNull()?.run {

                    val fine = fineLiveData.value ?: return

//                    if (quickFee > 0){
//                        val fee = quickFee
//                        quickDealLiveData.value?.run {
//                            quickPayment = true
//                            this.quickFee = fee
//                        }
//
//                        quickDealLiveData.reSend()
//
//                        //如果已经选中，更新价格
//                        if (fine.quickFee?.toFloat()?:0f > 0f){
//                            fine.setQuickFee(quickFee.toString())
//                        }
//
//                    }else{
//                        quickDealLiveData.value?.run {
//                            quickPayment = false
//                            quickFee = 0f
//                        }
//
//                        quickDealLiveData.reSend()
//
//                        fine.setQuickFee("0")
//                    }

                    //查询出来的金额不可以极速办理
                    quickDealLiveData.value?.run {
                        quickPayment = false
                        quickFee = 0f
                    }
                    quickDealLiveData.reSend()
                    fine.setQuickFee("0")


                    if (TextUtils.equals(fineDate, fine.fineDate) && StringUtils.parseToMoney(fineFee) == fine.fineFee) {
                        //时间和金额都一致
                        serviceFee?.let {
                            fine.setServiceFee(it)
                        }

                        lateFee?.let {
                            fine.setLateFee(it)
                        }

                        reSendFineData()
                    }
                } ?: kotlin.run {

                    quickDealLiveData.value?.run {
                        quickPayment = false
                        quickFee = 0f
                    }

                    quickDealLiveData.reSend()
                    fineLiveData.value?.setQuickFee("0")
                }

            }

            override fun onError(throwable: Throwable) {
                quickDealLiveData.value?.run {
                    quickPayment = false
                    quickFee = 0f
                }
                quickDealLiveData.reSend()

                fineLiveData.value?.setQuickFee("0")
            }

            override fun onComplete() {

            }
        }

        //服务费计算
        extraFeeLiveData.debounce(100L, TimeUnit.MILLISECONDS).switchMapSingle {
            Api.get().getFKDJExtraFee(it.fineFee?.toString(), it.fineDate)
        }.subscribe(extraFeeObserver)

        addRun(extraFeeObserver)

        //获取优惠券
        GlobalConfigManager.getInstance().reloadConfig()

    }

    //获取优惠券
    fun reloadCouponList() {
        val conf = GlobalConfigManager.getInstance().sysConf.couponActivityConf;
        if (TextUtils.equals(conf?.value, "1")) {
            addRun(Api.get().couponList().onResult(couponRespLiveData))
        }
    }

    fun checkFineArea(no: String) {
        addRun(Api.get().fineAreaHint(no).onResult({
            it?.run {
                if (!TextUtils.isEmpty(trim())) {
                    areaHintLiveData.postValue(trim())
                }
            }

        }, {

        }))
    }


    fun checkFine2(no: String, preFineInfo: PreFineInfo?) {
        preFineInfoLiveData.postValue(Resource.loading())
        fineQueryCount++
        saveFineNo(no)

        addRun(Api.get().checkFineNo(no).onResult({
            lastCheckNo = no
            //成功
            if (it != null && it.penaltyTime > 0) {

                //直接成功
                preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no, it.plateNumber,
                        it.party,
                        DateFormat.format("yyyy-MM-dd", it.penaltyTime * 1000).toString(),
                        it.fineFee.toString(),
                        it.serviceFee.toString(),
                        it.overdueFee.toString(),
                        it.quickFee.toString(),
                        null,
                        it.abnormalAreaHint,
                        it.quickFee > 0,
                        true
                )))

            } else {
                //没有结果

                addRun(Single.zip(checkFineFee(no, preFineInfo?.fineFee, preFineInfo?.fineDate),
                        checkFineAreaHint(no, preFineInfo?.fineFee, preFineInfo?.fineDate), object : BiFunction<Optional<FineExtraFeeResp?>, Optional<String?>, Optional<PreFineInfo>> {
                    override fun apply(t1: Optional<FineExtraFeeResp?>, t2: Optional<String?>): Optional<PreFineInfo> {
                        val hint = t2.orNull()?.trim()
                        val info = t1.orNull()?.let {
                            PreFineInfo(no,
                                    fineName = preFineInfo?.fineName,
                                    fineFee = it.fineFee,
                                    fineDate = it.fineDate,
                                    serviceFee = it.serviceFee,
                                    fineLateFee = it.lateFee,
                                    img = preFineInfo?.img,
                                    abnormalAreaHint = hint)
                        } ?: kotlin.run {
                            PreFineInfo(no, abnormalAreaHint = hint)
                        }
                        return Optional.ofNullable(info)
                    }
                }
                ).subscribe { t1, t2 ->
                    t1?.orNull()?.let {
                        preFineInfoLiveData.postValue(Resource.success(it))
                    } ?: kotlin.run {
                        preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no)))
                    }
                })

//                addRun(checkFineFee(no, preFineInfo?.fineFee, preFineInfo?.fineDate).subscribe { t1, t2 ->
//                    t1?.orNull()?.let {
//                        preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no,
//                                fineName = preFineInfo?.fineName,
//                                fineFee = it.fineFee,
//                                fineDate = it.fineDate,
//                                serviceFee = it.serviceFee,
//                                fineLateFee = it.lateFee,
//                                img = preFineInfo?.img)))
//                    }?:kotlin.run {
//                        preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no)))
//                    }
//                })
            }

        }, {

            //失败
            addRun(Single.zip(checkFineFee(no, preFineInfo?.fineFee, preFineInfo?.fineDate),
                    checkFineAreaHint(no, preFineInfo?.fineFee, preFineInfo?.fineDate), object : BiFunction<Optional<FineExtraFeeResp?>, Optional<String?>, Optional<PreFineInfo>> {
                override fun apply(t1: Optional<FineExtraFeeResp?>, t2: Optional<String?>): Optional<PreFineInfo> {
                    val hint = t2.orNull()?.trim()
                    val info = t1.orNull()?.let {
                        PreFineInfo(no,
                                fineName = preFineInfo?.fineName,
                                fineFee = it.fineFee,
                                fineDate = it.fineDate,
                                serviceFee = it.serviceFee,
                                fineLateFee = it.lateFee,
                                img = preFineInfo?.img,
                                abnormalAreaHint = hint)
                    } ?: kotlin.run {
                        PreFineInfo(no, abnormalAreaHint = hint)
                    }
                    return Optional.ofNullable(info)
                }

            }
            ).subscribe { t1, t2 ->
                t1?.orNull()?.let {
                    preFineInfoLiveData.postValue(Resource.success(it))
                } ?: kotlin.run {
                    preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no)))
                }
            })
//            addRun(checkFineFee(no, preFineInfo?.fineFee, preFineInfo?.fineDate).subscribe { t1, t2 ->
//
//                t1?.orNull()?.let {
//                    preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no,
//                            fineName = preFineInfo?.fineName,
//                            fineFee = it.fineFee,
//                            fineDate = it.fineDate,
//                            serviceFee = it.serviceFee,
//                            fineLateFee = it.lateFee,
//                            img = preFineInfo?.img)))
//                }?:kotlin.run {
//                    preFineInfoLiveData.postValue(Resource.success(PreFineInfo(no)))
//                }
//
//            })

        }))

    }

    private fun checkFineFee(no: String, fineFee: String? = null, fineDate: String?): Single<Optional<FineExtraFeeResp?>> {
        if (fineFee.isNullOrEmpty() || fineDate.isNullOrEmpty()) {
            return Single.just(Optional.absent())
        }
        return Api.get().getFKDJExtraFee(fineFee, fineDate)
    }

    private fun checkFineAreaHint(no: String, fineFee: String? = null, fineDate: String?): Single<Optional<String?>> {
        if (fineFee.isNullOrEmpty() || fineDate.isNullOrEmpty()) {
            return Single.just(Optional.absent())
        }
        return Api.get().fineAreaHint(no)
    }

    fun checkFine(no: String) {
        checkFineLiveData.postValue(Resource.loading())
        fineQueryCount++
        saveFineNo(no)
        addRun(Api.get().checkFineNo(no).timeout(15, TimeUnit.SECONDS).onResult({

            if (!TextUtils.isEmpty(it?.fineNumber?.trim())) {

                //识别成功
                StatTools.sendClick(AppContext.getContext(), StatisticsId.fkdj_code_identify_done)

                val queryFineData = FineData(true)
                it?.run {
                    queryFineData.fineNo = fineNumber?.trim()
                    queryFineData.fineName = party
                    queryFineData.carNo = plateNumber
                    queryFineData.fineDate = DateFormat.format("yyyy-MM-dd", penaltyTime * 1000).toString()
                    queryFineData.setFineFee(fineFee.toString())
                    queryFineData.setLateFee(overdueFee.toString())
                    queryFineData.setServiceFee(serviceFee.toString())

                    if (!TextUtils.isEmpty(abnormalAreaHint)) {
                        areaHintLiveData.postValue(abnormalAreaHint)
                    }

                    if (quickFee > 0) {
                        val f = quickFee
                        quickDealLiveData.value?.run {
                            quickPayment = true
                            this.quickFee = f
                        }

                        quickDealLiveData.reSend()
                    }

                }
                fineLiveData.value = queryFineData

                //val aaa = it
                checkFineLiveData.postValue(Resource.success(it))

                //checkFineLiveData.postValue(Resource.success(it))
            } else {

                StatTools.sendClick(AppContext.getContext(), StatisticsId.fkdj_code_identify_fail)

                // must call on main thread
                fineLiveData.postValue(FineData(false).apply {
                    fineNo = no
                })

                //不支持极速办理
                quickDealLiveData.value?.run {
                    quickPayment = false
                }
                quickDealLiveData.reSend()

//                fineLiveData.value?.run {
//                    reset()
//                    fineNo = no
//                }
                checkFineLiveData.postValue(Resource.success(null))
            }

        }, {

            StatTools.sendClick(AppContext.getContext(), StatisticsId.fkdj_code_identify_fail)

//            fineLiveData.value?.run {
//                fineNo = no
//            }

            fineLiveData.postValue(FineData(false).apply {
                fineNo = no
            })

            //不支持极速办理
            quickDealLiveData.value?.run {
                quickPayment = false
            }
            quickDealLiveData.reSend()

            checkFineLiveData.postValue(Resource.success(null))

        }))
    }


    fun setQuickDeal(quick: Boolean) {
        fineLiveData.value?.setQuickFee("0")

        quickDealLiveData.value?.run {

            if (quickPayment && quick) {
                fineLiveData.value?.setQuickFee(quickFee.toString())
            }
        }

        fineLiveData.reSend()
    }

    fun reSendFineData() {
        fineLiveData.reSend()
    }


    fun countTotalFee() {

        fineLiveData.value?.let {

            if (it.hasFineFee() && !TextUtils.isEmpty(it.fineDate)) {
                extraFeeLiveData.onNext(it)
            }

        }

    }

    fun checkFineNo(fineNo: String?, preFineInfo: PreFineInfo? = null): Boolean {
        if (fineNo.isNullOrEmpty()) {
            ToastUtils.showText("请输入罚单编号")
            return false
        }

        if (fineNo.length < 15) {
            ToastUtils.showText("请输入完整罚单编号")
            return false
        }

        val s = fineNo.subSequence(0, 2).toString().toIntOrNull() ?: 0

        if (s == 0 || s !in noPrefix) {
            ToastUtils.showText("罚单编号错误，请重新输入")
            return false
        }

        if (preFineInfo != null) {

            if (preFineInfo.fineName.isNullOrEmpty()) {
                ToastUtils.showText("请输入被处罚人姓名")
                return false
            }
            if (preFineInfo.fineDate.isNullOrEmpty()) {
                ToastUtils.showText("请选择处罚日期")
                return false
            }
            if (preFineInfo.fineFee.isNullOrEmpty()) {
                ToastUtils.showText("请输入罚款金额")
                return false
            }

            if (preFineInfo.fineFee.toDoubleOrNull() ?: 0.0 <= 0) {
                ToastUtils.showText("请输入罚款金额")
                return false
            }

            if (preFineInfo.img.isNullOrEmpty()) {
                ToastUtils.showText("请选择罚单照片")
                return false
            }
        }

        return true
    }


    fun saveFineNo(fineNo: String?) {
        if (fineNo.isNullOrEmpty()) {
            SPUtils.getInstance().remove(KEY_LAST_FINENO)
        } else {
            SPUtils.getInstance().put(KEY_LAST_FINENO, fineNo)
        }
    }

    fun getLastFineNo() = SPUtils.getInstance().getString(KEY_LAST_FINENO)

    fun getCheckFineLiveData(): LiveData<Resource<FinePaymentDetail?>> = checkFineLiveData

    fun getFineLiveData(): LiveData<FineData> = fineLiveData

    fun getFinePayConfig(): LiveData<FinePayConfig> = quickDealLiveData

    fun getAreaHintLiveData(): LiveData<String?> = areaHintLiveData

    fun getCouponRespLiveData(): LiveData<Resource<CouponResp?>> = couponRespLiveData


    fun getPreFineInfoLiveData(): LiveData<Resource<PreFineInfo?>> = preFineInfoLiveData

}